#include "Grammatical.h"

void grammatical::initGrammatical()
{
	dict["CompUnit"] = 1;
	dict["Decl"] = 2;
	dict["FuncDef"] = 3;
	dict["MainFuncDef"] = 4;
	dict["ConstDecl"] = 5;
	dict["VarDecl"] = 6;
	dict["FuncType"] = 7;
	dict["Ident"] = 8;
	dict["FuncFParams"] = 9;
	dict["Block"] = 10;
	dict["BType"] = 11;
	dict["VarDef"] = 12;
	dict["FuncFParam"] = 13;
	dict["BlockItem"] = 14;
	dict["ConstExp"] = 15;
	dict["InitVal"] = 16;
	dict["Stmt"] = 17;

	dict["AddExp"] = 18;
	dict["AddExpS"] = 76;

	dict["Exp"] = 19;
	dict["LVal"] = 20;
	dict["Cond"] = 21;
	dict["FormatString"] = 22;

	dict["MulExp"] = 23;
	dict["MulExpS"] = 77;

	dict["LOrExp"] = 24;
	dict["LOrExpS"] = 78;

	dict["LAndExp"] = 25;
	dict["LAndExpS"] = 79;

	dict["EqExp"] = 26;
	dict["EqExpS"] = 80;

	dict["UnaryExp"] = 27;

	dict["RelExp"] = 28;
	dict["RelExpS"] = 81;

	dict["PrimaryExp"] = 32;
	dict["FuncRParams"] = 33;
	dict["Number"] = 34;
	dict["IntConst"] = 35;
	dict["decimal-const"] = 36;
	dict["nonzero-digit"] = 37;
	dict["UnaryOp"] = 38;
	dict["ConstInitVal"] = 39;
	dict["ConstDef"] = 40;

	dict["main"] = 41;
	dict["const"] = 42;
	dict["int"] = 43;
	dict["break"] = 44;
	dict["continue"] = 45;
	dict["if"] = 46;
	dict["else"] = 47;
	dict["!"] = 48;
	dict["&&"] = 49;
	dict["||"] = 50;
	dict["while"] = 51;
	dict["getint"] = 52;
	dict["printf"] = 53;
	dict["return"] = 54;
	dict["+"] = 55;
	dict["-"] = 56;
	dict["void"] = 57;
	dict["*"] = 58;
	dict["/"] = 59;
	dict["%"] = 60;
	dict["<"] = 61;
	dict["<="] = 62;
	dict[">"] = 63;
	dict[">="] = 64;
	dict["=="] = 65;
	dict["!="] = 66;
	dict["="] = 67;
	dict[";"] = 68;
	dict[","] = 69;
	dict["("] = 70;
	dict[")"] = 71;
	dict["["] = 72;
	dict["]"] = 73;
	dict["{"] = 74;
	dict["}"] = 75;
}

std::pair<int, bool> grammatical::match(int type, int pos)
{
	if (pos == words.size())
		return {pos, true};
	std::pair<int, bool> original_pos = {pos, false};
	std::pair<int, bool> newpos;
	int size = answer.size();
	switch (type)
	{
	case 1: // CompUnit ::= {Decl} {FuncDef} MainFuncDef （0到正无穷）
		newpos = match(dict["Decl"], pos);
		// if second false, return original_pos 0
		// if second true, return newpos 1 or 1+...
		while (newpos.second)
		{
			pos = newpos.first;
			newpos = match(dict["Decl"], pos);
		}

		newpos = match(dict["FuncDef"], pos);
		while (newpos.second)
		{
			pos = newpos.first;
			newpos = match(dict["FuncDef"], pos);
		}

		newpos = match(dict["MainFuncDef"], pos);
		// if second false, return original_pos 0
		// if second true, return MainFuncDef correlation
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;
		answer.push_back({"CompUnit", ""});
		return {pos, true};
		break;
	case 2: // Decl（特选）
		newpos = match(dict["ConstDecl"], pos);
		// if second false, return original_pos 0
		// if second true, return ConstDecl correlation
		if (newpos.second)
			return newpos;

		newpos = match(dict["VarDecl"], pos);
		// if second false, return original_pos 0
		// if second true, return VarDecl correlation
		if (newpos.second)
			return newpos;

		while (answer.size() > size)
			answer.pop_back();
		return original_pos;
		break;
	case 3: // FuncDef (串行)
		newpos = match(dict["FuncType"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		// 锁定上一次匹配成功的位置
		pos = newpos.first;

		// 在匹配成功后继续匹配
		newpos = match(dict["Ident"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["("], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		pos = match(dict["FuncFParams"], pos).first;

		newpos = match(dict[")"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["Block"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"FuncDef", ""});
		return {pos, true};
		break;
	case 4: // MainFuncDef
		newpos = match(dict["int"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["main"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["("], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict[")"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["Block"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"MainFuncDef", ""});
		return {pos, true};
		break;
	case 5: // ConstDecl（，cycle 0到正无穷）
		newpos = match(dict["const"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["BType"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["ConstDef"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict[","], pos);
		while (newpos.second)
		{
			pos = newpos.first;

			newpos = match(dict["ConstDef"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;
			newpos = match(dict[","], pos);
		}
		newpos = match(dict[";"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"ConstDecl", ""});
		return {pos, true};
		break;
	case 6: // VarDecl
		newpos = match(dict["BType"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["VarDef"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict[","], pos);
		while (newpos.second)
		{
			pos = newpos.first;

			newpos = match(dict["VarDef"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict[","], pos);
		}

		newpos = match(dict[";"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"VarDecl", ""});
		return {pos, true};
		break;
	case 7: // FuncType（终端）
		newpos = match(dict["void"], pos);
		if (newpos.second)
		{
			answer.push_back({"FuncType", ""});
			return newpos;
		}

		newpos = match(dict["int"], pos);
		if (newpos.second)
		{
			answer.push_back({"FuncType", ""});
			return newpos;
		}
		newpos = match(dict["float"], pos);

		if (newpos.second)
		{
			answer.push_back({"FuncType", ""});
			return newpos;
		}

		while (answer.size() > size)
			answer.pop_back();
		return original_pos;
		break;
	case 8: // Ident (Part and Overall)
		if (words[pos].first == "IDENFR")
		{
			answer.push_back(words[pos]);
			return {pos + 1, true};
		}
		while (answer.size() > size)
			answer.pop_back();
		return original_pos;
		break;
	case 9: // FuncFParams
		newpos = match(dict["FuncFParam"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict[","], pos);
		while (newpos.second)
		{
			pos = newpos.first;

			newpos = match(dict["FuncFParam"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict[","], pos);
		}
		answer.push_back({"FuncFParams", ""});
		return {pos, true};
		break;
	case 10: // Block
		newpos = match(dict["{"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["BlockItem"], pos);
		while (newpos.second)
		{
			pos = newpos.first;
			newpos = match(dict["BlockItem"], pos);
		}

		newpos = match(dict["}"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"Block", ""});

		return {pos, true};
		break;
	case 11: // BType
		newpos = match(dict["int"], pos);
		if (newpos.second)
			return newpos;

		newpos = match(dict["float"], pos);
		if (newpos.second)
			return newpos;

		while (answer.size() > size)
			answer.pop_back();
		return original_pos;
		break;
	case 12: // VarDef
		newpos = match(dict["Ident"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["["], pos);
		while (newpos.second)
		{
			pos = newpos.first;

			newpos = match(dict["ConstExp"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict["]"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict["["], pos);
		}

		newpos = match(dict["="], pos);
		if (!newpos.second)
		{
			answer.push_back({"VarDef", ""});
			return {pos, true};
		}
		pos = newpos.first;

		newpos = match(dict["InitVal"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"VarDef", ""});
		return {pos, true};
		break;
	case 13: // FuncFParam（方括号内的成分为任选项）,部分可选
		newpos = match(dict["BType"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["Ident"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["["], pos);
		if (!newpos.second)
		{
			answer.push_back({"FuncFParam", ""});
			return {pos, true};
		}
		pos = newpos.first;

		newpos = match(dict["]"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["["], pos);
		while (newpos.second)
		{
			pos = newpos.first;

			newpos = match(dict["ConstExp"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict["]"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict["["], pos);
		}

		answer.push_back({"FuncFParam", ""});
		return {pos, true};
		break;
	case 14: // BlockItem
		newpos = match(dict["Decl"], pos);
		if (newpos.second)
			return newpos;

		newpos = match(dict["Stmt"], pos);
		if (newpos.second)
			return newpos;

		while (answer.size() > size)
			answer.pop_back();
		return original_pos;
		break;
	case 15: // ConstExp
		newpos = match(dict["AddExp"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"ConstExp", ""});
		return {pos, true};
		break;
	case 16: // InitVal (Choice1,multiple)
		newpos = match(dict["Exp"], pos);
		if (newpos.second)
		{
			answer.push_back({"InitVal", ""});
			return newpos;
		}

		newpos = match(dict["{"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["InitVal"], pos);
		if (newpos.second)
		{
			pos = newpos.first;
			newpos = match(dict[","], pos);
			while (newpos.second)
			{
				pos = newpos.first;

				newpos = match(dict["InitVal"], pos);
				if (!newpos.second)
				{
					while (answer.size() > size)
						answer.pop_back();
					return original_pos;
				}
				pos = newpos.first;
				newpos = match(dict[","], pos);
			}
		}
		newpos = match(dict["}"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"InitVal", ""});
		return {pos, true};
		break;
	case 17: // Stmt
		newpos = match(dict["LVal"], pos);
		if (newpos.second)
		{
			pos = newpos.first;

			newpos = match(dict["="], pos);
			if (newpos.second)
			{
				pos = newpos.first;

				newpos = match(dict["Exp"], pos);
				if (newpos.second)
				{
					pos = newpos.first;

					newpos = match(dict[";"], pos);
					if (!newpos.second)
					{
						while (answer.size() > size)
							answer.pop_back();
						return original_pos;
					}
					pos = newpos.first;

					answer.push_back({"Stmt", ""});
					return {pos, true};
				}

				newpos = match(dict["getint"], pos);
				if (!newpos.second)
				{
					while (answer.size() > size)
						answer.pop_back();
					return original_pos;
				}
				pos = newpos.first;

				newpos = match(dict["("], pos);
				if (!newpos.second)
				{
					while (answer.size() > size)
						answer.pop_back();
					return original_pos;
				}
				pos = newpos.first;

				newpos = match(dict[")"], pos);
				if (!newpos.second)
				{
					while (answer.size() > size)
						answer.pop_back();
					return original_pos;
				}
				pos = newpos.first;

				newpos = match(dict[";"], pos);
				if (!newpos.second)
				{
					while (answer.size() > size)
						answer.pop_back();
					return original_pos;
				}
				pos = newpos.first;

				answer.push_back({"Stmt", ""});
				return {pos, true};
			}
		}
		pos = original_pos.first;
		while (answer.size() > size)
			answer.pop_back();
		newpos = match(dict["Block"], pos);
		if (newpos.second)
		{
			answer.push_back({"Stmt", ""});
			return newpos;
		}
		newpos = match(dict["if"], pos);
		if (newpos.second)
		{
			pos = newpos.first;

			newpos = match(dict["("], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict["Cond"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict[")"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict["Stmt"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict["else"], pos);
			if (newpos.second)
			{
				pos = newpos.first;
				newpos = match(dict["Stmt"], pos);
				if (!newpos.second)
				{
					while (answer.size() > size)
						answer.pop_back();
					return original_pos;
				}
				pos = newpos.first;
				answer.push_back({"Stmt", ""});
				return {pos, true};
			}
			else
			{
				answer.push_back({"Stmt", ""});
				return {pos, true};
			}
		}
		newpos = match(dict["while"], pos);
		if (newpos.second)
		{
			pos = newpos.first;

			newpos = match(dict["("], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict["Cond"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict[")"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict["Stmt"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;
			answer.push_back({"Stmt", ""});
			return {pos, true};
		}
		newpos = match(dict["break"], pos);
		if (newpos.second)
		{
			pos = newpos.first;

			newpos = match(dict[";"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;
			answer.push_back({"Stmt", ""});
			return {pos, true};
		}
		newpos = match(dict["continue"], pos);
		if (newpos.second)
		{
			pos = newpos.first;

			newpos = match(dict[";"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;
			answer.push_back({"Stmt", ""});
			return {pos, true};
		}
		newpos = match(dict["return"], pos);
		if (newpos.second)
		{
			pos = newpos.first;

			pos = match(dict["Exp"], pos).first;

			newpos = match(dict[";"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;
			answer.push_back({"Stmt", ""});
			return {pos, true};
		}
		newpos = match(dict["printf"], pos);
		if (newpos.second)
		{
			pos = newpos.first;

			newpos = match(dict["("], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict["FormatString"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict[","], pos);
			while (newpos.second)
			{
				pos = newpos.first;

				newpos = match(dict["Exp"], pos);
				if (!newpos.second)
				{
					while (answer.size() > size)
						answer.pop_back();
					return original_pos;
				}
				pos = newpos.first;

				newpos = match(dict[","], pos);
			}

			newpos = match(dict[")"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict[";"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;
			answer.push_back({"Stmt", ""});
			return {pos, true};
		}
		pos = match(dict["Exp"], pos).first;

		newpos = match(dict[";"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"Stmt", ""});
		return {pos, true};
		break;

		// AddExp->MulExp AddExpS
		// AddExpS->('+'|'-')MulExp AddExpS | e

	case 18: // AddExp
		newpos = match(dict["MulExp"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["AddExpS"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"AddExp", ""});
		return {pos, true};
		break;
	case 76: // AddExpS
		answer.push_back({"AddExp", ""});
		if (match(dict["+"], pos).second)
			pos++;
		else if (match(dict["-"], pos).second)
			pos++;
		else
		{
			answer.pop_back();
			return {pos, true};
		}

		newpos = match(dict["MulExp"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["AddExpS"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		return {pos, true};
		break;
	case 19: // Exp
		newpos = match(dict["AddExp"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"Exp", ""});
		return {pos, true};
		break;
	case 20: // LVal
		newpos = match(dict["Ident"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["["], pos);
		while (newpos.second)
		{
			pos = newpos.first;

			newpos = match(dict["Exp"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict["]"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict["["], pos);
		}
		answer.push_back({"LVal", ""});
		return {pos, true};
		break;
	case 21: // Cond
		newpos = match(dict["LOrExp"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"Cond", ""});
		return {pos, true};
		break;
	case 22: // FormatString
		if (words[pos].first == "STRCON")
		{
			answer.push_back(words[pos]);
			return {pos + 1, true};
		}
		else
			return {pos, false};
		break;

	// MulExp->UnaryExp MulExpS
	// MulExpS->('*'|'/'|'%')UnaryExp MulExpS | e
	case 23: // MulExp
		newpos = match(dict["UnaryExp"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["MulExpS"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"MulExp", ""});
		return {pos, true};
		break;
	case 77: // MulExpS
		answer.push_back({"MulExp", ""});
		if (match(dict["*"], pos).second)
			pos++;
		else if (match(dict["/"], pos).second)
			pos++;
		else if (match(dict["%"], pos).second)
			pos++;
		else
		{
			answer.pop_back();
			return {pos, true};
		}

		newpos = match(dict["UnaryExp"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["MulExpS"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		return {pos, true};
		break;

	// LOrExp->LAndExp LOrExpS
	// LOrExpS->'||'LAndExp LOrExpS | e
	case 24: // LOrExp
		newpos = match(dict["LAndExp"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["LOrExpS"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"LOrExp", ""});
		return {pos, true};
		break;
	case 78: // LOrExps
		answer.push_back({"LOrExp", ""});
		newpos = match(dict["||"], pos);
		if (!newpos.second)
		{
			answer.pop_back();
			return {pos, true};
		}
		pos = newpos.first;

		newpos = match(dict["LAndExp"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["LOrExpS"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		return {pos, true};
		break;

	// LAndExp->EqExp LAndExpS
	// LAndExpS->'&&'EqExp LAndExpS | e
	case 25: // LAndExp
		newpos = match(dict["EqExp"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["LAndExpS"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"LAndExp", ""});
		return {pos, true};
		break;
	case 79: // LAndExpS
		answer.push_back({"LAndExp", ""});
		newpos = match(dict["&&"], pos);
		if (!newpos.second)
		{
			answer.pop_back();
			return {pos, true};
		}
		pos = newpos.first;

		newpos = match(dict["EqExp"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["LAndExpS"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		return {pos, true};
		break;

	// EqExp->RelExp EqExpS
	// EqExpS->('=='|'!=')RelExp EqExpS | e
	case 26: // EqExp
		newpos = match(dict["RelExp"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["EqExpS"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"EqExp", ""});
		return {pos, true};
		break;
	case 80: // EqExpS
		answer.push_back({"EqExp", ""});
		if (match(dict["=="], pos).second)
			pos++;
		else if (match(dict["!="], pos).second)
			pos++;
		else
		{
			answer.pop_back();
			return {pos, true};
		}

		newpos = match(dict["RelExp"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["EqExpS"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		return {pos, true};
		break;
	case 27: // UnaryExp

		newpos = match(dict["UnaryOp"], pos);
		if (newpos.second)
		{
			pos = newpos.first;

			newpos = match(dict["UnaryExp"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			answer.push_back({"UnaryExp", ""});
			return {pos, true};
		}

		newpos = match(dict["Ident"], pos);
		if (newpos.second)
		{
			pos = newpos.first;

			newpos = match(dict["("], pos);
			if (newpos.second)
			{
				pos = newpos.first;

				pos = match(dict["FuncRParams"], pos).first;

				newpos = match(dict[")"], pos);
				if (!newpos.second)
				{
					while (answer.size() > size)
						answer.pop_back();
					return original_pos;
				}
				pos = newpos.first;
				answer.push_back({"UnaryExp", ""});
				return {pos, true};
			}
		}

		pos = original_pos.first;
		while (answer.size() > size)
			answer.pop_back();
		newpos = match(dict["PrimaryExp"], pos);
		if (newpos.second)
		{
			answer.push_back({"UnaryExp", ""});
			return newpos;
		}
		else
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		break;

	// RelExp->AddExp RelExpS
	// RelExpS->('<'|'>'|'<='|'>=')AddExp RelExpS | e
	case 28: // RelExp
		newpos = match(dict["AddExp"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["RelExpS"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"RelExp", ""});
		return {pos, true};
		break;
	case 81: // RelExps

		answer.push_back({"RelExp", ""});
		if (match(dict["<"], pos).second)
			pos++;
		else if (match(dict[">"], pos).second)
			pos++;
		else if (match(dict["<="], pos).second)
			pos++;
		else if (match(dict[">="], pos).second)
			pos++;
		else
		{
			answer.pop_back();
			return {pos, true};
		}

		newpos = match(dict["AddExp"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["RelExpS"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		return {pos, true};
		break;
	case 32: // PrimaryExp
		newpos = match(dict["Number"], pos);
		if (newpos.second)
		{
			answer.push_back({"PrimaryExp", ""});
			return newpos;
		}

		newpos = match(dict["LVal"], pos);
		if (newpos.second)
		{
			answer.push_back({"PrimaryExp", ""});
			return newpos;
		}

		newpos = match(dict["("], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["Exp"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict[")"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"PrimaryExp", ""});
		return {pos, true};
		break;
	case 33: // FuncRParams
		newpos = match(dict["Exp"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict[","], pos);
		while (newpos.second)
		{
			pos = newpos.first;

			newpos = match(dict["Exp"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict[","], pos);
		}
		answer.push_back({"FuncRParams", ""});
		return {pos, true};
		break;
	case 34: // Number
		newpos = match(dict["IntConst"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;
		answer.push_back({"Number", ""});
		return {pos, true};
		break;
	case 35: // IntConst
		if (words[pos].first == "INTCON")
		{
			answer.push_back(words[pos]);
			return {pos + 1, true};
		}
		else
			return {pos, false};
		break;
	case 36: // decimal-const
	case 37: // nonzero-digit
	case 38: // UnaryOp
		if (match(dict["+"], pos).second)
			pos++;
		else if (match(dict["-"], pos).second)
			pos++;
		else if (match(dict["!"], pos).second)
			pos++;
		else
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		answer.push_back({"UnaryOp", ""});
		return {pos, true};
		break;
	case 39: // ConstInitVal
		newpos = match(dict["ConstExp"], pos);
		if (newpos.second)
		{
			answer.push_back({"ConstInitVal", ""});
			return newpos;
		}

		newpos = match(dict["{"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["ConstInitVal"], pos);
		if (newpos.second)
		{
			pos = newpos.first;

			newpos = match(dict[","], pos);
			while (newpos.second)
			{
				pos = newpos.first;

				newpos = match(dict["ConstInitVal"], pos);
				if (!newpos.second)
				{
					while (answer.size() > size)
						answer.pop_back();
					return original_pos;
				}
				pos = newpos.first;

				newpos = match(dict[","], pos);
			}
		}

		newpos = match(dict["}"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"ConstInitVal", ""});
		return {pos, true};
		break;
	case 40: // ConstDef
		newpos = match(dict["Ident"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		newpos = match(dict["["], pos);
		while (newpos.second)
		{
			pos = newpos.first;

			newpos = match(dict["ConstExp"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict["]"], pos);
			if (!newpos.second)
			{
				while (answer.size() > size)
					answer.pop_back();
				return original_pos;
			}
			pos = newpos.first;

			newpos = match(dict["["], pos);
		}
		newpos = match(dict["="], pos);
		if (!newpos.second)
		{
			answer.push_back({"ConstDef", ""});
			return {pos, true};
		}

		pos = newpos.first;

		newpos = match(dict["ConstInitVal"], pos);
		if (!newpos.second)
		{
			while (answer.size() > size)
				answer.pop_back();
			return original_pos;
		}
		pos = newpos.first;

		answer.push_back({"ConstDef", ""});
		return {pos, true};
		break;
	default:
		if (words[pos].second == str[type - 40])
		{
			answer.push_back(words[pos]);
			return {pos + 1, true};
		}
		else
			return {pos, false};
		break;
	}
}

std::vector<std::pair<std::string, std::string>> grammatical::analysis(std::vector<std::pair<std::string, std::string>> context)
{
	answer.clear();
	words = context;
	int pos = match(dict["CompUnit"], 0).first;
	return answer;
}